package com.liumuxian.web.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import entity.Result;
import entity.StatusCode;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import util.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 前台网关的自定义过滤器
 */
@Component
public class WebZuulFilter extends ZuulFilter {
    @Override
    public String filterType() {
        //过滤器的类型
        return "pre";//前置过滤器
    }

    @Override
    public int filterOrder() {
        //过滤器的顺序，根据数字的大小排序调用，数字越小，越先调用
        return 0;//第一个执行
    }

    @Override
    public boolean shouldFilter() {
        //该过滤器是否开启有效
        return true;//开启的
    }
    //注入Jwt工具类
    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Object run() throws ZuulException {
        //过滤器的具体的业务逻辑代码
        System.out.println("web前台网关，经过了zuul前置过滤器...");
        //目标：获取头信息，改个名字，向下转发
        //1.获取头信息
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        //约定：前端传过来的头信息：Authorization
        String authorizationHeader = request.getHeader("Authorization");

        //2. 其他请求处理
        //1）处理CORS跨域请求，因为跨域请求的第一次请求是预请求，不带头信息的，因此要过滤掉。
        if(request.getMethod().equals("OPTIONS")){
            System.out.println("跨域的第一次请求，直接放行");
            return null;
        }
        //2）处理一些特殊请求，比如登录请求，就直接放行
        //获取请求的URL
        String url=request.getRequestURL().toString();
        //如果是管理员登录
        if(url.indexOf("/wx/login")>0){
            System.out.println("微信用户的登录请求，直接放行："+url);
            return null;
        }


        //2.判断，改名，转发
        if(null !=authorizationHeader){
            requestContext.addZuulRequestHeader("JwtAuthorization",authorizationHeader);
            requestContext.addZuulRequestHeader("Authorization",authorizationHeader);//照样过滤掉了，无效
            //获取令牌，The part after "Bearer "
            final String token=authorizationHeader.substring(7);
            //获取载荷
            Claims claims = null;
            try {
                claims = jwtUtil.parseJWT(token);
            } catch (Exception e) {
                e.printStackTrace();
            }

            //判断载荷是否为空
            if(null != claims && ("admin".equals(claims.get("roles"))||"user".equals(claims.get("roles")))){
                //是管理员身份的请求
                //转发头信息到具体微服务
                requestContext.addZuulRequestHeader("JwtAuthorization",authorizationHeader);
                //放行
                return null;
            }
        }

        //如果没有权限，则：
        //终止转发请求，直接响应
        requestContext.setSendZuulResponse(false);

        //友好的提示
//        requestContext.getResponse().setContentType("text/html;charset=UTF-8");
//        requestContext.setResponseBody("您无权访问");
        requestContext.getResponse().setContentType("application/json;charset=UTF-8");
//        requestContext.setResponseBody("{\"flag\":false,\"code\":20003,\"message\":\"您无权访问\"}");
        try {
            requestContext.setResponseBody(objectMapper.writeValueAsString(new Result(false, StatusCode.ACCESSERROR, "用户登录！")));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        //http的响应码:401或403
        requestContext.setResponseStatusCode(403);

        try {
            String str = objectMapper.writeValueAsString(new Result(false, StatusCode.ACCESSERROR, "用户登录！"));
            System.out.println(str);
            Result result = objectMapper.readValue(str, Result.class);
            System.out.println(result.getMsg());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //放行
        return null;
    }
}
